from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

db = SQLAlchemy()

class User(db.Model):
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(50), unique=True, nullable=False, index=True)
    email = db.Column(db.String(100), unique=True, nullable=True)
    password = db.Column(db.String(200), nullable=False)
    name = db.Column(db.String(100), nullable=False)  # 真实姓名
    role = db.Column(db.String(20), default='student')  # student, teacher, admin
    department = db.Column(db.String(100), nullable=True)  # 部门/班级
    status = db.Column(db.String(20), default='active')  # active, inactive, banned
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    last_activity = db.Column(db.DateTime, default=datetime.utcnow)  # 最后活动时间
    
    # 关系
    courses = db.relationship('Course', backref='teacher', lazy=True)
    homeworks = db.relationship('Homework', backref='teacher', lazy=True)
    submissions = db.relationship('Submission', backref='student', lazy=True)
    # 班级关系
    managed_classes = db.relationship('Class', backref='teacher', lazy=True, foreign_keys='Class.teacher_id')
    enrolled_classes = db.relationship('Class', secondary='class_student', backref='students', lazy=True)
    
    def to_dict(self):
        return {
            'id': self.id,
            'username': self.username,
            'email': self.email,
            'name': self.name,
            'role': self.role,
            'department': self.department,
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else datetime.utcnow().isoformat()
        }

class Course(db.Model):
    __tablename__ = 'courses'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(100), nullable=False)
    code = db.Column(db.String(20), unique=True, nullable=False)  # 课程代码
    description = db.Column(db.Text, nullable=True)
    teacher_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    status = db.Column(db.String(20), default='active')  # active, inactive
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关系
    homeworks = db.relationship('Homework', backref='course', lazy=True)
    
    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'code': self.code,
            'description': self.description,
            'teacher_id': self.teacher_id,
            'teacher_name': self.teacher.name if self.teacher else None,
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else datetime.utcnow().isoformat()
        }

class Problem(db.Model):
    __tablename__ = 'problems'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False)
    description = db.Column(db.Text, nullable=False)
    type = db.Column(db.String(20), nullable=False)  # choice, blank, code, short
    difficulty = db.Column(db.String(20), default='medium')  # easy, medium, hard
    answer = db.Column(db.Text, nullable=True)
    test_cases = db.Column(db.Text, nullable=True)  # JSON字符串
    options = db.Column(db.Text, nullable=True)  # 选择题选项，JSON字符串
    input_format = db.Column(db.Text, nullable=True)  # 输入格式说明
    output_format = db.Column(db.Text, nullable=True)  # 输出格式说明
    points = db.Column(db.Integer, default=10)  # 分值
    time_limit = db.Column(db.Integer, default=1000)  # 时间限制(ms)
    memory_limit = db.Column(db.Integer, default=64)  # 内存限制(MB)
    language = db.Column(db.String(20), default='python')  # python, cpp, java
    created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    status = db.Column(db.String(20), default='active')  # active, inactive
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关系
    submissions = db.relationship('Submission', backref='problem', lazy=True)
    
    def to_dict(self):
        import json
        return {
            'id': self.id,
            'title': self.title,
            'description': self.description,
            'type': self.type,
            'difficulty': self.difficulty,
            'answer': self.answer,
            'test_cases': json.loads(self.test_cases) if self.test_cases else [],
            'options': json.loads(self.options) if self.options else [],
            'input_format': self.input_format,
            'output_format': self.output_format,
            'points': self.points,
            'time_limit': self.time_limit,
            'memory_limit': self.memory_limit,
            'language': self.language,
            'created_by': self.created_by,
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else datetime.utcnow().isoformat()
        }

class Homework(db.Model):
    __tablename__ = 'homeworks'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=True)
    course_id = db.Column(db.Integer, db.ForeignKey('courses.id'), nullable=False)
    problems = db.Column(db.Text, nullable=False)  # JSON字符串存储题目ID列表
    start_time = db.Column(db.DateTime, nullable=True)
    deadline = db.Column(db.DateTime, nullable=True)
    total_points = db.Column(db.Integer, default=0)
    teacher_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    status = db.Column(db.String(20), default='active')  # active, inactive, draft
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关系
    submissions = db.relationship('Submission', backref='homework', lazy=True)
    
    def to_dict(self):
        import json
        return {
            'id': self.id,
            'title': self.title,
            'description': self.description,
            'course_id': self.course_id,
            'course_name': self.course.name if self.course else None,
            'problems': json.loads(self.problems) if self.problems else [],
            'start_time': self.start_time.isoformat() if self.start_time else None,
            'deadline': self.deadline.isoformat() if self.deadline else None,
            'total_points': self.total_points,
            'teacher_id': self.teacher_id,
            'teacher_name': self.teacher.name if self.teacher else None,
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else datetime.utcnow().isoformat()
        }

class Submission(db.Model):
    __tablename__ = 'submissions'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    homework_id = db.Column(db.Integer, db.ForeignKey('homeworks.id'), nullable=False)
    problem_id = db.Column(db.Integer, db.ForeignKey('problems.id'), nullable=False)
    student_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    answer = db.Column(db.Text, nullable=False)  # 答案（代码或文本）
    language = db.Column(db.String(20), nullable=True)  # 编程语言
    status = db.Column(db.String(20), default='Pending')  # Pending, AC, WA, RE, TLE, CE
    score = db.Column(db.Float, default=0.0)  # 得分
    execution_time = db.Column(db.Integer, nullable=True)  # 执行时间(ms)
    memory_used = db.Column(db.Integer, nullable=True)  # 内存使用(KB)
    error_message = db.Column(db.Text, nullable=True)  # 错误信息
    test_results = db.Column(db.Text, nullable=True)  # 测试结果，JSON字符串
    submit_time = db.Column(db.DateTime, default=datetime.utcnow)
    
    def to_dict(self):
        import json
        return {
            'id': self.id,
            'homework_id': self.homework_id,
            'problem_id': self.problem_id,
            'student_id': self.student_id,
            'student_name': self.student.name if self.student else None,
            'answer': self.answer,
            'language': self.language,
            'status': self.status,
            'score': self.score,
            'execution_time': self.execution_time,
            'memory_used': self.memory_used,
            'error_message': self.error_message,
            'test_results': json.loads(self.test_results) if self.test_results else [],
            'submit_time': self.submit_time.isoformat() if self.submit_time else datetime.utcnow().isoformat()
        }

class SystemLog(db.Model):
    __tablename__ = 'system_logs'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    type = db.Column(db.String(20), nullable=False)  # info, warning, error, success
    message = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    ip_address = db.Column(db.String(45), nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    def to_dict(self):
        return {
            'id': self.id,
            'type': self.type,
            'message': self.message,
            'user_id': self.user_id,
            'user_name': self.user.name if self.user else '系统',
            'ip_address': self.ip_address,
            'created_at': self.created_at.isoformat() if self.created_at else datetime.utcnow().isoformat()
        }

# 班级-学生关联表
class_student = db.Table('class_student',
    db.Column('class_id', db.Integer, db.ForeignKey('classes.id'), primary_key=True),
    db.Column('student_id', db.Integer, db.ForeignKey('users.id'), primary_key=True)
)

class Class(db.Model):
    """班级模型"""
    __tablename__ = 'classes'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(100), nullable=False, comment='班级名称')
    description = db.Column(db.Text, comment='班级描述')
    teacher_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='班主任ID')
    max_students = db.Column(db.Integer, default=50, comment='最大学生数')
    status = db.Column(db.String(20), default='active', comment='班级状态：active/inactive')
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, comment='更新时间')
    
    # 关联关系
    assignments = db.relationship('Assignment', backref='class_obj', lazy=True, cascade='all, delete-orphan')
    
    def __repr__(self):
        return f'<Class {self.name}>'
    
    def to_dict(self):
        """转换为字典"""
        return {
            'id': self.id,
            'name': self.name,
            'description': self.description,
            'teacher_id': self.teacher_id,
            'teacher_name': self.teacher.name if self.teacher else None,
            'max_students': self.max_students,
            'current_students': len(self.students),
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None
        }
    
    def to_dict_with_students(self):
        """转换为包含学生信息的字典"""
        data = self.to_dict()
        data['students'] = [student.to_dict() for student in self.students]
        return data

class Assignment(db.Model):
    """作业模型"""
    __tablename__ = 'assignments'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False, comment='作业标题')
    description = db.Column(db.Text, comment='作业描述')
    class_id = db.Column(db.Integer, db.ForeignKey('classes.id'), nullable=False, comment='班级ID')
    problem_ids = db.Column(db.Text, comment='关联的题目ID列表，JSON格式')
    due_date = db.Column(db.DateTime, nullable=False, comment='截止时间')
    total_score = db.Column(db.Float, default=100.0, comment='总分')
    status = db.Column(db.String(20), default='active', comment='作业状态：active/expired/completed')
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, comment='更新时间')
    
    # 关联关系
    submissions = db.relationship('AssignmentSubmission', backref='assignment', lazy=True, cascade='all, delete-orphan')
    
    def __repr__(self):
        return f'<Assignment {self.title}>'
    
    def to_dict(self):
        """转换为字典"""
        return {
            'id': self.id,
            'title': self.title,
            'description': self.description,
            'class_id': self.class_id,
            'class_name': self.class_obj.name if self.class_obj else None,
            'problem_ids': self.problem_ids,
            'due_date': self.due_date.isoformat() if self.due_date else None,
            'total_score': self.total_score,
            'status': self.status,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None,
            'submission_count': len(self.submissions)
        }
    
    def is_expired(self):
        """检查作业是否已过期"""
        return datetime.utcnow() > self.due_date
    
    def get_submission_stats(self):
        """获取提交统计信息"""
        total_students = len(self.class_obj.students) if self.class_obj else 0
        submitted_count = len(self.submissions)
        return {
            'total_students': total_students,
            'submitted_count': submitted_count,
            'submission_rate': (submitted_count / total_students * 100) if total_students > 0 else 0
        }

class AssignmentSubmission(db.Model):
    """作业提交模型"""
    __tablename__ = 'assignment_submissions'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    assignment_id = db.Column(db.Integer, db.ForeignKey('assignments.id'), nullable=False, comment='作业ID')
    student_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='学生ID')
    problem_id = db.Column(db.Integer, db.ForeignKey('problems.id'), nullable=False, comment='题目ID')
    code = db.Column(db.Text, comment='提交的代码')
    language = db.Column(db.String(20), default='python', comment='编程语言')
    status = db.Column(db.String(20), default='pending', comment='提交状态：pending/running/accepted/wrong_answer/time_limit/memory_limit/compile_error')
    score = db.Column(db.Float, default=0.0, comment='得分')
    execution_time = db.Column(db.Float, comment='执行时间(ms)')
    memory_usage = db.Column(db.Float, comment='内存使用(MB)')
    error_message = db.Column(db.Text, comment='错误信息')
    submitted_at = db.Column(db.DateTime, default=datetime.utcnow, comment='提交时间')
    graded_at = db.Column(db.DateTime, comment='批改时间')
    graded_by = db.Column(db.Integer, db.ForeignKey('users.id'), comment='批改教师ID')
    feedback = db.Column(db.Text, comment='教师反馈')
    
    # 关联关系
    student = db.relationship('User', foreign_keys=[student_id])
    problem = db.relationship('Problem')
    grader = db.relationship('User', foreign_keys=[graded_by])
    
    def __repr__(self):
        return f'<AssignmentSubmission {self.assignment_id}-{self.student_id}-{self.problem_id}>'
    
    def to_dict(self):
        """转换为字典"""
        return {
            'id': self.id,
            'assignment_id': self.assignment_id,
            'assignment_title': self.assignment.title if self.assignment else None,
            'student_id': self.student_id,
            'student_name': self.student.name if self.student else None,
            'problem_id': self.problem_id,
            'problem_title': self.problem.title if self.problem else None,
            'code': self.code,
            'language': self.language,
            'status': self.status,
            'score': self.score,
            'execution_time': self.execution_time,
            'memory_usage': self.memory_usage,
            'error_message': self.error_message,
            'submitted_at': self.submitted_at.isoformat() if self.submitted_at else None,
            'graded_at': self.graded_at.isoformat() if self.graded_at else None,
            'graded_by': self.graded_by,
            'grader_name': self.grader.name if self.grader else None,
            'feedback': self.feedback
        }
    
    def is_late(self):
        """检查是否逾期提交"""
        if self.assignment and self.assignment.due_date:
            return self.submitted_at > self.assignment.due_date
        return False
